<?php
/**
 * FastApp.
 * 1/3/25
 * @Author deepsea
 * @Contact (telegram:deepsea159)
 */

namespace App\Fastapp\Process\CryptoTransfer;

use App\Fastapp\Api\Service\Crypto\Config;
use App\Fastapp\Job\WalletAddressTransactionJob;
use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
use Hyperf\WebSocketClient\Client;
use Hyperf\WebSocketClient\ClientFactory;
use Hyperf\WebSocketClient\Frame;

#[Process(name: 'BnbListenerProcess')]
class BnbListenerProcess extends AbstractProcess
{
    public Client $client;

    public function stop(): bool
    {
        return $this->client->close();
    }

    public function isEnable($server): bool
    {
        return false;
//        return env('APP_ENV') == 'prod';
    }

    public function handle(): void
    {
        // Binance Smart Chain (BEP-20)
        $this->start();
    }

    public function initClient(): void
    {
        $this->client = container()->get(ClientFactory::class)->create('wss://' . Config::BNB_URL, false);
        $this->client->push(json_encode([
            'jsonrpc' => '2.0',
            'id' => time(),
            'method' => 'eth_subscribe',
            'params' => ['newHeads'],
        ]));
        $this->client->push(json_encode([
            'jsonrpc' => '2.0',
            'id' => 1,
            'method' => 'eth_subscribe',
            'params' => [
                'logs',
                [
                    'address' => Config::BEP20_CONTRACT_ADDRESS_USDT,
                    'topics' => [
                        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // Transfer 事件的 Keccak256 哈希
                        null,
                        null
                    ],
                ],
            ],
        ]));
    }

    public function formatData(): void
    {
        $tranETH = $tranUsdt = [];
        while (true) {
            try {
                /** @var Frame $frame */
                $frame = $this->client->recv();
            } catch (\Throwable) {
                return;
            }
            if ($frame) {
                $response = json_decode($frame->data, true);
                if (isset($response['method']) && $response['method'] == 'eth_subscription' && isset($response['params']['result']['hash'])) {
                    $this->client->push(json_encode([
                        'jsonrpc' => '2.0',
                        'id' => time(),
                        'method' => 'eth_getBlockByHash',
                        'params' => [$response['params']['result']['hash'], true],
                    ]));
                } else if (isset($response['result']['transactions'])) {
                    foreach ($response['result']['transactions'] as $tx) {
                        if (!empty($tx['from']) && !empty($tx['to'])) {
                            if (hexdec($tx['value']) > 0 && ($tx['input'] === '0x' || $tx['input'] === '0x0')) {
                                $tranETH[] = [
                                    'txid' => $tx['hash'],
                                    'from' => $tx['from'],
                                    'to' => $tx['to'],
                                    'value' => hexdec($tx['value']) / 1e18,
                                ];
                            }
                        }
                    }
                } elseif (isset($response['params']['result']['topics'])) {
                    $tranUsdt[] = [
                        'txid' => $response['params']['result']['transactionHash'],
                        'from' => '0x' . substr($response['params']['result']['topics'][1], 26),
                        'to' => '0x' . substr($response['params']['result']['topics'][2], 26),
                        'value' => hexdec($response['params']['result']['data']) / 1e6,// USDT 精度为 6
                    ];
                }
            }
            if (count($tranETH) > 50) {
                $this->handleEvent($tranETH, 'to');//充值
                $this->handleEvent($tranETH, 'from');//提现
                $tranETH = [];
            }
            if (count($tranUsdt) > 50) {
                $this->handleEvent($tranUsdt, 'to', 'USDT');//充值
                $this->handleEvent($tranUsdt, 'from', 'USDT');//提现
                $tranUsdt = [];
            }
        }
    }

    private function handleEvent(array $receivedTransactions, string $field, ?string $symbol_token = null): void
    {
        WalletAddressTransactionJob::log($receivedTransactions, 'BNB', $field, $symbol_token);
    }

    public function start(): void
    {
        $this->initClient();
        $this->formatData();
        $this->start();
    }
}